<!DOCTYPE html>
<html lang="zh_cn">
<head>
          <title>来玩魔王的咚</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta charset="utf-8" />
        <!-- twitter card metadata -->
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="/images/mowang.png">
<meta name="twitter:site" content="">
<meta name="twitter:title" content="Docker 基础知识">
<meta name="twitter:description" content="<p>容器基础：Namespaces，cgroups；构架：daemon，client，registries；安装：Docker-CE，指定版本，镜像加速器，配置文件；命令：系统信息，搜索镜像；image镜像操作：拉取镜像，查看下载的镜像，删除本地镜像；container容器操作：run命令，busybox容器操作</p>">
        <!-- OG Tags -->
<meta property="og:url" content="/docker-basic-knowledge.html"/>
<meta property="og:title" content="来玩魔王的咚 | Docker 基础知识" />
<meta property="og:description" content="<p>容器基础：Namespaces，cgroups；构架：daemon，client，registries；安装：Docker-CE，指定版本，镜像加速器，配置文件；命令：系统信息，搜索镜像；image镜像操作：拉取镜像，查看下载的镜像，删除本地镜像；container容器操作：run命令，busybox容器操作</p>" />
        <!-- favicon -->
        <link rel="icon" type="image/png" href="/images/mowang.png">
        <!-- moment.js for date formatting -->
        <script src="/theme/js/moment.js"></script>
        <!-- css -->
        <link rel="stylesheet" type="text/css" href="/theme/css/main.css" />
        <!-- 左边的menu，如果页面高度不够，就跟着滚动，否则文章分类显示不全 -->
        <link rel="stylesheet" type="text/css" href="/theme/css/mycss/menu.css" />
		<script>
			
                /*! grunt-grunticon Stylesheet Loader - v2.1.2 | https://github.com/filamentgroup/grunticon | (c) 2015 Scott Jehl, Filament Group, Inc. | MIT license. */
    
    (function(e){function t(t,n,r,o){"use strict";function a(){for(var e,n=0;u.length>n;n++)u[n].href&&u[n].href.indexOf(t)>-1&&(e=!0);e?i.media=r||"all":setTimeout(a)}var i=e.document.createElement("link"),l=n||e.document.getElementsByTagName("script")[0],u=e.document.styleSheets;return i.rel="stylesheet",i.href=t,i.media="only x",i.onload=o||null,l.parentNode.insertBefore(i,l),a(),i}var n=function(r,o){"use strict";if(r&&3===r.length){var a=e.navigator,i=e.Image,l=!(!document.createElementNS||!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect||!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1")||e.opera&&-1===a.userAgent.indexOf("Chrome")||-1!==a.userAgent.indexOf("Series40")),u=new i;u.onerror=function(){n.method="png",n.href=r[2],t(r[2])},u.onload=function(){var e=1===u.width&&1===u.height,a=r[e&&l?0:e?1:2];n.method=e&&l?"svg":e?"datapng":"png",n.href=a,t(a,null,null,o)},u.src="",document.documentElement.className+=" grunticon"}};n.loadCSS=t,e.grunticon=n})(this);(function(e,t){"use strict";var n=t.document,r="grunticon:",o=function(e){if(n.attachEvent?"complete"===n.readyState:"loading"!==n.readyState)e();else{var t=!1;n.addEventListener("readystatechange",function(){t||(t=!0,e())},!1)}},a=function(e){return t.document.querySelector('link[href$="'+e+'"]')},c=function(e){var t,n,o,a,c,i,u={};if(t=e.sheet,!t)return u;n=t.cssRules?t.cssRules:t.rules;for(var l=0;n.length>l;l++)o=n[l].cssText,a=r+n[l].selectorText,c=o.split(");")[0].match(/US\-ASCII\,([^"']+)/),c&&c[1]&&(i=decodeURIComponent(c[1]),u[a]=i);return u},i=function(e){var t,o,a;o="data-grunticon-embed";for(var c in e)if(a=c.slice(r.length),t=n.querySelectorAll(a+"["+o+"]"),t.length)for(var i=0;t.length>i;i++)t[i].innerHTML=e[c],t[i].style.backgroundImage="none",t[i].removeAttribute(o);return t},u=function(t){"svg"===e.method&&o(function(){i(c(a(e.href))),"function"==typeof t&&t()})};e.embedIcons=i,e.getCSS=a,e.getIcons=c,e.ready=o,e.svgLoadedCallback=u,e.embedSVG=u})(grunticon,this);
                
                grunticon(["/theme/css/icons.data.svg.css", "/theme/css/icons.data.png.css", "/theme/css/icons.fallback.css"]);
            </script>
        <noscript><link href="/theme/css/icons.fallback.css" rel="stylesheet"></noscript>
        <!-- menu toggle javascript -->
        <script type="text/javascript">
            document.addEventListener("DOMContentLoaded", initMenu);
            
            function initMenu(){
                var menu = document.getElementById("menu");
                var menulink = document.getElementById("menu-link");
                menulink.addEventListener("click", function toggleMenu(){
                        window.event.preventDefault();
                        menulink.classList.toggle('active');
                        menu.classList.toggle('active');              
                    });
            };
        </script>
        <!-- 不蒜子 -->
        <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

    <meta name="description" content="<p>容器基础：Namespaces，cgroups；构架：daemon，client，registries；安装：Docker-CE，指定版本，镜像加速器，配置文件；命令：系统信息，搜索镜像；image镜像操作：拉取镜像，查看下载的镜像，删除本地镜像；container容器操作：run命令，busybox容器操作</p>" />

    <meta name="tags" content="docker" />
  <!-- 替换部分base的样式，看文章时，要再宽一点，右边有很多空间可以撑开 -->
  <link rel="stylesheet" type="text/css" href="/theme/css/mycss/article.css" />

</head>
<body>
    <div role="banner" id="masthead">
        <header>
            <a href="/"><img src="/images/mowang.png" alt="McManus Logo"></a>
                <h1>来玩魔王的咚@骑士救兵</h1>
            <a href="#menu" id="menu-link">more stuff</a>
            <nav id="menu">
                <ul>
                        <li><a href="/tags">tags</a></li>
                            <li><a href="/category/cloud.html">Cloud</a></li>
                            <li class="active"><a href="/category/docker.html">Docker</a></li>
                            <li><a href="/category/go.html">Go</a></li>
                            <li><a href="/category/linux.html">Linux</a></li>
                            <li><a href="/category/python.html">Python</a></li>
                            <li><a href="/category/xue-xi-bi-ji.html">学习笔记</a></li>
                            <li><a href="/category/yun-wei-zi-dong-hua.html">运维自动化</a></li>
                </ul>
            </nav>
        </header>
    </div>
        <div class="page" role="main">
  <div class="article" role="article">
    <article>
        <footer>
            <a name="top"></a>
            <p>
              <time datetime=" 2020-07-22 09:00:00+08:00">
                <script>document.write(moment('2020-07-22 09:00:00+08:00').format('LL'));</script>
              </time>
              ~
              <time datetime=" 2020-07-22 09:00:00+08:00">
                <script>document.write(moment('2020-07-22 09:00:00+08:00').format('LL'));</script>
              </time>
            </p>
        </footer>
        <header>
          <h2>
            Docker 基础知识
          </h2>
        </header>
      <div class="content">
         <div class="toc">
<ul>
<li><a href="#rong-qi-ji-chu-zhi-shi">容器基础知识</a><ul>
<li><a href="#namespaces">Namespaces</a></li>
<li><a href="#control-groupscgroups">Control Groups(cgroups)</a></li>
<li><a href="#rong-qi-bian-pai-gong-ju">容器编排工具</a></li>
</ul>
</li>
<li><a href="#docker-jia-gou">Docker 架构</a><ul>
<li><a href="#docker-daemon">Docker daemon</a></li>
<li><a href="#docker-client">Docker client</a></li>
<li><a href="#docker-registries">Docker registries</a></li>
</ul>
</li>
<li><a href="#an-zhuang-docker">安装docker</a><ul>
<li><a href="#centos-guan-fang-yuan">CentOS官方源</a></li>
<li><a href="#docker-de-ban-ben">Docker的版本</a></li>
<li><a href="#tian-jia-docker-ce-yuan">添加Docker-CE源</a></li>
<li><a href="#zhu-yi-ban-ben-jian-rong-xing">注意版本兼容性</a></li>
<li><a href="#an-zhuang-zhi-ding-ban-ben-de-docker">安装指定版本的docker</a></li>
<li><a href="#shi-yong-jing-xiang-jia-su-qi">使用镜像加速器</a></li>
<li><a href="#pei-zhi-wen-jian">配置文件</a></li>
</ul>
</li>
<li><a href="#docker-ming-ling">Docker 命令</a><ul>
<li><a href="#zi-ming-ling">子命令</a></li>
<li><a href="#go-ming-ling-de-diao-yong-liu-cheng">Go 命令的调用流程</a></li>
<li><a href="#xiang-xi-xi-tong-xin-xi">详细系统信息</a></li>
<li><a href="#networ-wang-luo">networ 网络</a></li>
<li><a href="#sou-suo-jing-xiang">搜索镜像</a></li>
</ul>
</li>
<li><a href="#image-jing-xiang-cao-zuo">image 镜像操作</a><ul>
<li><a href="#la-qu-jing-xiang">拉取镜像</a></li>
<li><a href="#cha-kan-xia-zai-de-jing-xiang">查看下载的镜像</a></li>
<li><a href="#shan-chu-ben-di-jing-xiang">删除本地镜像</a></li>
</ul>
</li>
<li><a href="#container-rong-qi-cao-zuo">container 容器操作</a><ul>
<li><a href="#run-ming-ling">run 命令</a></li>
<li><a href="#busybox">busybox</a></li>
<li><a href="#xiao-jie">小结</a></li>
</ul>
</li>
</ul>
</div>
<h3 id="rong-qi-ji-chu-zhi-shi"><a class="toclink" href="#rong-qi-ji-chu-zhi-shi">容器基础知识</a></h3>
<p>容器级虚拟化，不再为每一个虚拟机创建单独的内核，而是通过在宿主机的内核上将6种资源通过内核机制（namespaces）隔离出来，每一个namespace就是一个单独的容器。<br>
Linux领域的容器技术，就是靠内核级的6个namespaces、chroot和Cgroups共同实现的。  </p>
<h4 id="namespaces"><a class="toclink" href="#namespaces">Namespaces</a></h4>
<p>隔离用户空间，将进程与其他进程隔离开来。</p>
<table>
<thead>
<tr>
<th align="left">namesapce</th>
<th align="left">系统调用参数</th>
<th align="left">隔离内容</th>
<th align="left">内核版本</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Mount</td>
<td align="left">CLONE_NEWNW</td>
<td align="left">挂载点（文件系统）</td>
<td align="left">2.4.19</td>
</tr>
<tr>
<td align="left">UTS</td>
<td align="left">CLONE_NEWUTS</td>
<td align="left">主机名和域名</td>
<td align="left">2.6.19</td>
</tr>
<tr>
<td align="left">IPC</td>
<td align="left">CLONE_NEWIPC</td>
<td align="left">信号量、消息队列和共享内存</td>
<td align="left">2.6.19</td>
</tr>
<tr>
<td align="left">PID</td>
<td align="left">CLONE_NEWPID</td>
<td align="left">进程编号</td>
<td align="left">2.6.24</td>
</tr>
<tr>
<td align="left">Network</td>
<td align="left">CLONE_NEWNET</td>
<td align="left">网络设备、网络栈、端口等</td>
<td align="left">2.6.29</td>
</tr>
<tr>
<td align="left">User</td>
<td align="left">CLONE_NEWUSER</td>
<td align="left">用户和用户组</td>
<td align="left">3.8</td>
</tr>
</tbody>
</table>
<p>最后一个是在内核的3.8版本才加入到内核中的。所以要想很好的使用容器技术，内核版本需要在3.8之后，也就是需要Centos7。  </p>
<h4 id="control-groupscgroups"><a class="toclink" href="#control-groupscgroups">Control Groups(cgroups)</a></h4>
<p>容器化技术的隔离机制是靠namespaces实现，而容器化的资源分配靠的是在内核级通过CGroups机制实现。它会把系统级的资源分成多个组，然后把每一个组内的资源量指派分配到特定的namespace的进程上去。<br>
cgroups，资源限制，限制进程占用的CPU和内存:</p>
<ul>
<li>blkio: 块设备IO</li>
<li>cpu: CPU</li>
<li>cpuacct: CPU资源使用报告</li>
<li>cpuset: 多处理器平台上的CPU集合</li>
<li>devices: 设备访问</li>
<li>freezer: 挂起或恢复任务</li>
<li>memory: 内存用量及报告</li>
<li>perf_event: 对cgroup中的任务进行统一性能测试</li>
<li>net_cls: cgroup中的任务创建的数据报文的类别标识符</li>
</ul>
<p><strong>CPU属于可压缩资源。内存属于非可压缩资源，绝对不允许越界。</strong>  </p>
<h4 id="rong-qi-bian-pai-gong-ju"><a class="toclink" href="#rong-qi-bian-pai-gong-ju">容器编排工具</a></h4>
<p>Docker三大编排工具：</p>
<ul>
<li>Docker Compose：是用来组装多容器应用的工具，可以在 Swarm集群中部署分布式应用。</li>
<li>Docker Swarm：是Docker社区原生提供的容器集群管理工具。</li>
<li>Docker Machine：是支持多平台安装Docker的工具，可以很方便地在笔记本、云平台及数据中心里安装Docker。</li>
</ul>
<p>Compose是单机版。Swarm是集群管理工具。  </p>
<p>以上这些可能都用不到，因为最流行的还是下面这个。<br>
kubernetes：简称K8s，Google开源的一个容器编排引擎。  </p>
<p>k8s需要作为一个单独的主题，另外再去学习的工具，这里只是把工具的名称引出来。  </p>
<h3 id="docker-jia-gou"><a class="toclink" href="#docker-jia-gou">Docker 架构</a></h3>
<p>Docker架构如下，有3个部分组成。<br>
<img alt="Docker架构" src="/images/docker/01_docker-frame.png"></p>
<p>这里有Client端和Server端（DOCKER_HOST），所以这是一个C/S架构的应用程序。  </p>
<h4 id="docker-daemon"><a class="toclink" href="#docker-daemon">Docker daemon</a></h4>
<p>Docker deamon运行为守护进程。所以运行后这台主机就变成了守护进程服务器。<br>
Docker daemon 监听UNIX套接字或网络接口。默认只监听本地的UNIX套接字。  </p>
<p><strong>Images 镜像</strong>，可以从registries下载镜像。所有镜像都是只读的。<br>
<strong>Containers 容器</strong>，启动容器时是基于镜像来启动。  </p>
<h4 id="docker-client"><a class="toclink" href="#docker-client">Docker client</a></h4>
<p>客户端是用户操作Docker的主要方式。docker命令使用Docker API，客户端可以与多个daemon进行通信。  </p>
<h4 id="docker-registries"><a class="toclink" href="#docker-registries">Docker registries</a></h4>
<p>Docker的镜像仓库。<br>
Docker Hub（ https://hub.docker.com/ ），官方提供的镜像仓库，在国外。建议使用国内镜像。  </p>
<h3 id="an-zhuang-docker"><a class="toclink" href="#an-zhuang-docker">安装docker</a></h3>
<p>在Centos7上使用yum安装docker。  </p>
<h4 id="centos-guan-fang-yuan"><a class="toclink" href="#centos-guan-fang-yuan">CentOS官方源</a></h4>
<p>CentOS官方源就有docker，注意这里用的名称是docker:</p>
<div class="highlight"><pre><span></span><code>$ yum info docker
已加载插件：fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.163.com
可安装的软件包
名称    ：docker
架构    ：x86_64
时期       ：2
版本    ：1.13.1
发布    ：96.gitb2f74b2.el7.centos
大小    ：18 M
源    ：extras/7/x86_64
简介    ： Automates deployment of containerized applications
网址    ：https://github.com/docker/docker
协议    ： ASL <span class="m">2</span>.0
描述    ： Docker is an open-source engine that automates the deployment of any
         : application as a lightweight, portable, self-sufficient container that will
         : run virtually anywhere.
         : 
         : Docker containers can encapsulate any payload, and will run consistently on
         : and between virtually any server. The same container that a developer builds
         : and tests on a laptop will run at scale, <span class="k">in</span> production*, on VMs, bare-metal
         : servers, OpenStack clusters, public instances, or combinations of the above.

$ 
</code></pre></div>

<p>但是这个的版本太低了，所以不使用CentOS的源。  </p>
<h4 id="docker-de-ban-ben"><a class="toclink" href="#docker-de-ban-ben">Docker的版本</a></h4>
<p>现在Docker软件主要有两个版本：</p>
<ul>
<li>Docker-CE: 社区版本，这是一个免费的版本</li>
<li>Docker-EE: 企业版本，这是一个付费的版本</li>
</ul>
<p>Docker另外还有一个开源的版本Moby，这个也是从原先的docker项目继承过来，是社区维护的。而Docker-CE是Docoker公司维护的开源项目。  </p>
<h4 id="tian-jia-docker-ce-yuan"><a class="toclink" href="#tian-jia-docker-ce-yuan">添加Docker-CE源</a></h4>
<p>这里添加阿里的镜像源，这个是社区版Docker-CE：</p>
<div class="highlight"><pre><span></span><code>$ wget -P /etc/yum.repos.d/ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
</code></pre></div>

<p>检查版本信息，注意这里用的名称是docker-ce:</p>
<div class="highlight"><pre><span></span><code>$ yum info docker-ce
已加载插件：fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
可安装的软件包
名称    ：docker-ce
架构    ：x86_64
时期       ：3
版本    ：18.09.7
发布    ：3.el7
大小    ：19 M
源    ：docker-ce-stable/x86_64
简介    ： The open-source application container engine
网址    ：https://www.docker.com
协议    ： ASL <span class="m">2</span>.0
描述    ： Docker is is a product <span class="k">for</span> you to build, ship and run any application as a
         : lightweight container.
         : 
         : Docker containers are both hardware-agnostic and platform-agnostic. This means
         : they can run anywhere, from your laptop to the largest cloud compute instance and
         : everything <span class="k">in</span> between - and they don<span class="err">&#39;</span>t require you to use a particular
         : language, framework or packaging system. That makes them great building blocks
         : <span class="k">for</span> deploying and scaling web apps, databases, and backend services without
         : depending on a particular stack or provider.

$
</code></pre></div>

<h4 id="zhu-yi-ban-ben-jian-rong-xing"><a class="toclink" href="#zhu-yi-ban-ben-jian-rong-xing">注意版本兼容性</a></h4>
<p>上面显示的最新版本信息是18.09.7，由于docker一般还要配合容器编排工具使用，现在最流行的就是k8s。而k8s还不一定支持最新版本，所以具体要安装那个版本，还得确认一下版本的依赖关系。<br>
查询k8s对docker版本的依赖关系，可以到Github的k8s的项目中，项目地址：<br>
https://github.com/kubernetes/kubernetes<br>
查询版本的CHANGELOG，比如这个文件CHANGELOG-1.15.md。文件内容比较多，直接搜索“Docker version”：  </p>
<blockquote>
<p>The list of validated docker versions remains unchanged. <br>
The current list is 1.13.1, 17.03, 17.06, 17.09, 18.06, 18.09. (#72823, #72831)  </p>
</blockquote>
<h4 id="an-zhuang-zhi-ding-ban-ben-de-docker"><a class="toclink" href="#an-zhuang-zhi-ding-ban-ben-de-docker">安装指定版本的docker</a></h4>
<p>这里就安装一个不是最新的18.06版本。  </p>
<h5 id="an-zhuang-zhi-ding-ban-ben"><a class="toclink" href="#an-zhuang-zhi-ding-ban-ben">安装指定版本</a></h5>
<p>首先查询有哪些版本可用，查询版本命令如下:</p>
<div class="highlight"><pre><span></span><code>$ yum list docker-ce --showduplicates <span class="p">|</span> expand
已加载插件：fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
可安装的软件包
docker-ce.x86_64            <span class="m">17</span>.03.0.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            <span class="m">17</span>.03.1.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            <span class="m">17</span>.03.2.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            <span class="m">17</span>.03.3.ce-1.el7                    docker-ce-stable
docker-ce.x86_64            <span class="m">17</span>.06.0.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            <span class="m">17</span>.06.1.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            <span class="m">17</span>.06.2.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            <span class="m">17</span>.09.0.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            <span class="m">17</span>.09.1.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            <span class="m">17</span>.12.0.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            <span class="m">17</span>.12.1.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            <span class="m">18</span>.03.0.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            <span class="m">18</span>.03.1.ce-1.el7.centos             docker-ce-stable
docker-ce.x86_64            <span class="m">18</span>.06.0.ce-3.el7                    docker-ce-stable
docker-ce.x86_64            <span class="m">18</span>.06.1.ce-3.el7                    docker-ce-stable
docker-ce.x86_64            <span class="m">18</span>.06.2.ce-3.el7                    docker-ce-stable
docker-ce.x86_64            <span class="m">18</span>.06.3.ce-3.el7                    docker-ce-stable
docker-ce.x86_64            <span class="m">3</span>:18.09.0-3.el7                     docker-ce-stable
docker-ce.x86_64            <span class="m">3</span>:18.09.1-3.el7                     docker-ce-stable
docker-ce.x86_64            <span class="m">3</span>:18.09.2-3.el7                     docker-ce-stable
docker-ce.x86_64            <span class="m">3</span>:18.09.3-3.el7                     docker-ce-stable
docker-ce.x86_64            <span class="m">3</span>:18.09.4-3.el7                     docker-ce-stable
docker-ce.x86_64            <span class="m">3</span>:18.09.5-3.el7                     docker-ce-stable
docker-ce.x86_64            <span class="m">3</span>:18.09.6-3.el7                     docker-ce-stable
docker-ce.x86_64            <span class="m">3</span>:18.09.7-3.el7                     docker-ce-stable
$ 
</code></pre></div>

<p><em>expand 命令的效果只是让输出更加紧凑一点，把制表符换成空格。</em></p>
<p>选择合适的版本进行安装，命令如下:</p>
<div class="highlight"><pre><span></span><code>yum install docker-ce-18.06.0.ce-3.el7
</code></pre></div>

<h5 id="qi-dong-he-yan-zheng"><a class="toclink" href="#qi-dong-he-yan-zheng">启动和验证</a></h5>
<p>启动服务、开机启动，查看版本信息：</p>
<div class="highlight"><pre><span></span><code>$ systemctl start docker.service
$ systemctl <span class="nb">enable</span> docker.service
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
$ docker version
Client:
 Version:           <span class="m">18</span>.06.0-ce
 API version:       <span class="m">1</span>.38
 Go version:        go1.10.3
 Git commit:        0ffa825
 Built:             Wed Jul <span class="m">18</span> <span class="m">19</span>:08:18 <span class="m">2018</span>
 OS/Arch:           linux/amd64
 Experimental:      <span class="nb">false</span>

Server:
 Engine:
  Version:          <span class="m">18</span>.06.0-ce
  API version:      <span class="m">1</span>.38 <span class="o">(</span>minimum version <span class="m">1</span>.12<span class="o">)</span>
  Go version:       go1.10.3
  Git commit:       0ffa825
  Built:            Wed Jul <span class="m">18</span> <span class="m">19</span>:10:42 <span class="m">2018</span>
  OS/Arch:          linux/amd64
  Experimental:     <span class="nb">false</span>
$
</code></pre></div>

<p>这里能分别看到Client端和Server端各自的版本。Docker是用Go语言开发的，这里有显示Go的版本。另外还有平台的版本<code>linux/amd64</code>，这个之后使用或下载其他组件时，遇到有平台相关的版本兼容性问题，可以根据这个选择对应的版本。  </p>
<h4 id="shi-yong-jing-xiang-jia-su-qi"><a class="toclink" href="#shi-yong-jing-xiang-jia-su-qi">使用镜像加速器</a></h4>
<p>默认的镜像仓库在国外，最好使用在国内的官方镜像站点。这里列出了几个：</p>
<ul>
<li>阿里云的加速器：https://help.aliyun.com/document_detail/60750.html</li>
<li>网易加速器：http://hub-mirror.c.163.com</li>
<li>官方中国加速器：https://registry.docker-cn.com</li>
<li>中国科技大学的镜像：https://docker.mirrors.ustc.edu.cn</li>
</ul>
<p>阿里云的不能直接使用，因为需要注册，效果应该会很不错。<br>
docker-cn虽然是官方的，但是加速效果也很差。<em>大概是不了解国情。</em><br>
网易和中科大的都可以使用。<br>
使用配置文件/etc/docker/daemon.json，如果目录或文件没有，就手动创建。在配置文件中添加如下内容：</p>
<div class="highlight"><pre><span></span><code><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nt">&quot;registry-mirrors&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;http://hub-mirror.c.163.com&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;https://registry.docker-cn.com&quot;</span><span class="p">]</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>

<p>这里的配置使用的是JSON格式。要是配置生效，需要重启服务。  </p>
<h4 id="pei-zhi-wen-jian"><a class="toclink" href="#pei-zhi-wen-jian">配置文件</a></h4>
<p>上面只是使用了一个配置项，完整的配置项信息可以查看官方的文档：<br>
https://docs.docker.com/engine/reference/commandline/dockerd/#Daemon-configuration-file<br>
应该是所有的配置项都在这里了，之后需要的时候可以再来查阅。  </p>
<h3 id="docker-ming-ling"><a class="toclink" href="#docker-ming-ling">Docker 命令</a></h3>
<p>不使用任何参数执行 docker 打印的帮助信息如下：</p>
<div class="highlight"><pre><span></span><code>$ docker

Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default &quot;/root/.docker&quot;)
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level (&quot;debug&quot;|&quot;info&quot;|&quot;warn&quot;|&quot;error&quot;|&quot;fatal&quot;) (default &quot;info&quot;)
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default &quot;/root/.docker/ca.pem&quot;)
      --tlscert string     Path to TLS certificate file (default &quot;/root/.docker/cert.pem&quot;)
      --tlskey string      Path to TLS key file (default &quot;/root/.docker/key.pem&quot;)
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  config      Manage Docker configs
  container   Manage containers
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container&#39;s changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container&#39;s filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container&#39;s filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Run &#39;docker COMMAND --help&#39; for more information on a command.
$ 
</code></pre></div>

<h4 id="zi-ming-ling"><a class="toclink" href="#zi-ming-ling">子命令</a></h4>
<p>这里有 Management Commands 和 Commands。docker有很多子命令，早期的docker是Commands风格的，每一个子命令都是单独的。现在命令多了，为这些子命令分了很多组进行管理，这个就是Management Commands。<br>
所以两种命令风格效果是一样的。比如，下面两个命令是一样的：</p>
<div class="highlight"><pre><span></span><code>docker run
docker container run
</code></pre></div>

<p>建议尽量使用 Management Commands 的命令。</p>
<h4 id="go-ming-ling-de-diao-yong-liu-cheng"><a class="toclink" href="#go-ming-ling-de-diao-yong-liu-cheng">Go 命令的调用流程</a></h4>
<p>这里是题外话，这么好的命令行界面，好奇是具体怎么做的。<br>
使用了golang命令行库cobra：https://github.com/spf13/cobra。<br>
具体可以看下这篇文章的分析：https://www.jianshu.com/p/9900ec52f2c1。<br>
有一点可能需要注意，Docker的设计是Client-Server模式的，平时我们用的docker这个命令被分散到 https://github.com/docker/cli 这个仓库去了。  </p>
<h4 id="xiang-xi-xi-tong-xin-xi"><a class="toclink" href="#xiang-xi-xi-tong-xin-xi">详细系统信息</a></h4>
<p>之前使用<code>docker version</code>命令，查看了版本信息，这个使用<code>docker info</code>命令可以查看更详细的信息：</p>
<div class="highlight"><pre><span></span><code>$ docker system info
Containers: 0  // 总的容器数量
 Running: 0    // 运行状态的容器数量
 Paused: 0     // 暂停状态的容器数量
 Stopped: 0    // 停止状态的容器数量
Images: 0      // 镜像的数量
Server Version: 18.06.0-ce  // 服务器版本
Storage Driver: overlay2    // 存储驱动后端
 Backing Filesystem: xfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:  // 插件
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: d64c661f1d51c48782c9cec8fda7604785f93587
runc version: 69663f0bd4b60df09991c08812a60108003fa340
init version: fec3683
Security Options:  // 安全选项
 seccomp
  Profile: default
Kernel Version: 3.10.0-957.el7.x86_64  // 内核版本
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 908.2MiB
Name: Docker
ID: HB7V:B35V:AGQR:Z4JM:WLZ3:T53Y:DXAD:R3HE:OIMS:ODXL:QKDB:MQES
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Registry Mirrors:  // 镜像加速器
 http://hub-mirror.c.163.com/
 https://registry.docker-cn.com/
Live Restore Enabled: false

$ 
</code></pre></div>

<p>以上部分信息，我用类似注释的方式在对应的行里加了说明。  </p>
<h4 id="networ-wang-luo"><a class="toclink" href="#networ-wang-luo">networ 网络</a></h4>
<p>查看容器可以使用的网络：</p>
<div class="highlight"><pre><span></span><code>$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
39cd19b7d266        bridge              bridge              <span class="nb">local</span>
d086953087bb        host                host                <span class="nb">local</span>
fa0c7f1fb6ca        none                null                <span class="nb">local</span>
$
</code></pre></div>

<p>容器网络的内容也是需要单独展开的，这里只是演示一下网络命令。  </p>
<h4 id="sou-suo-jing-xiang"><a class="toclink" href="#sou-suo-jing-xiang">搜索镜像</a></h4>
<p>可以使用命令来搜索镜像：<code>docker search</code>。这个命令不属于任何一个Management Commands，所以就直接这么用：</p>
<div class="highlight"><pre><span></span><code>$ docker search nginx
</code></pre></div>

<p>命令的输出结果贴出来不是很好看，下面是利用--format参数，输出完整的JSON格式的内容：</p>
<div class="highlight"><pre><span></span><code>$ docker search nginx --limit <span class="m">5</span> --format <span class="s1">&#39;{{json .}}&#39;</span>
<span class="o">{</span><span class="s2">&quot;Description&quot;</span>:<span class="s2">&quot;Official build of Nginx.&quot;</span>,<span class="s2">&quot;IsAutomated&quot;</span>:<span class="s2">&quot;false&quot;</span>,<span class="s2">&quot;IsOfficial&quot;</span>:<span class="s2">&quot;true&quot;</span>,<span class="s2">&quot;Name&quot;</span>:<span class="s2">&quot;nginx&quot;</span>,<span class="s2">&quot;StarCount&quot;</span>:<span class="s2">&quot;11680&quot;</span><span class="o">}</span>
<span class="o">{</span><span class="s2">&quot;Description&quot;</span>:<span class="s2">&quot;Automated Nginx reverse proxy for docker con…&quot;</span>,<span class="s2">&quot;IsAutomated&quot;</span>:<span class="s2">&quot;true&quot;</span>,<span class="s2">&quot;IsOfficial&quot;</span>:<span class="s2">&quot;false&quot;</span>,<span class="s2">&quot;Name&quot;</span>:<span class="s2">&quot;jwilder/nginx-proxy&quot;</span>,<span class="s2">&quot;StarCount&quot;</span>:<span class="s2">&quot;1627&quot;</span><span class="o">}</span>
<span class="o">{</span><span class="s2">&quot;Description&quot;</span>:<span class="s2">&quot;Container running Nginx + PHP-FPM capable of…&quot;</span>,<span class="s2">&quot;IsAutomated&quot;</span>:<span class="s2">&quot;true&quot;</span>,<span class="s2">&quot;IsOfficial&quot;</span>:<span class="s2">&quot;false&quot;</span>,<span class="s2">&quot;Name&quot;</span>:<span class="s2">&quot;richarvey/nginx-php-fpm&quot;</span>,<span class="s2">&quot;StarCount&quot;</span>:<span class="s2">&quot;726&quot;</span><span class="o">}</span>
<span class="o">{</span><span class="s2">&quot;Description&quot;</span>:<span class="s2">&quot;Bitnami nginx Docker Image&quot;</span>,<span class="s2">&quot;IsAutomated&quot;</span>:<span class="s2">&quot;true&quot;</span>,<span class="s2">&quot;IsOfficial&quot;</span>:<span class="s2">&quot;false&quot;</span>,<span class="s2">&quot;Name&quot;</span>:<span class="s2">&quot;bitnami/nginx&quot;</span>,<span class="s2">&quot;StarCount&quot;</span>:<span class="s2">&quot;69&quot;</span><span class="o">}</span>
<span class="o">{</span><span class="s2">&quot;Description&quot;</span>:<span class="s2">&quot;NGINX Ingress Controller for Kubernetes&quot;</span>,<span class="s2">&quot;IsAutomated&quot;</span>:<span class="s2">&quot;false&quot;</span>,<span class="s2">&quot;IsOfficial&quot;</span>:<span class="s2">&quot;false&quot;</span>,<span class="s2">&quot;Name&quot;</span>:<span class="s2">&quot;nginx/nginx-ingress&quot;</span>,<span class="s2">&quot;StarCount&quot;</span>:<span class="s2">&quot;20&quot;</span><span class="o">}</span>
</code></pre></div>

<p>这里不但获取了所有的字段的内容，还有每个字段的字段名。  </p>
<p>现在还可以调整--format参数，自定义输出的格式：</p>
<div class="highlight"><pre><span></span><code>$ docker search nginx --limit <span class="m">5</span> --format <span class="s1">&#39;{{.Name}}\t{{.Description}}\t{{.StarCount}}\t{{.IsOfficial | printf &quot;%q&quot;}}\t{{.IsAutomated | printf &quot;%q&quot;}}&#39;</span>
nginx   Official build of Nginx.        <span class="m">11680</span>   <span class="s2">&quot;[OK]&quot;</span>  <span class="s2">&quot;&quot;</span>
jwilder/nginx-proxy     Automated Nginx reverse proxy <span class="k">for</span> docker con…   <span class="m">1627</span>    <span class="s2">&quot;&quot;</span>      <span class="s2">&quot;[OK]&quot;</span>
richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of…   <span class="m">726</span>     <span class="s2">&quot;&quot;</span>      <span class="s2">&quot;[OK]&quot;</span>
bitnami/nginx   Bitnami nginx Docker Image      <span class="m">69</span>      <span class="s2">&quot;&quot;</span>      <span class="s2">&quot;[OK]&quot;</span>
nginx/nginx-ingress     NGINX Ingress Controller <span class="k">for</span> Kubernetes <span class="m">20</span>      <span class="s2">&quot;&quot;</span>      <span class="s2">&quot;&quot;</span>
$ 
</code></pre></div>

<p>默认输出的内容如果太长，会被截断，比如Description字段。这时可以使用--no-trunc参数，阻止内容被截断。  </p>
<p>不过搜索的结构没有详细的tag信息，所以这个命令没太大用处。要搜索镜像就直接上 hub.docker.com 查。  </p>
<p><strong>Docker Hub 搜索镜像</strong><br>
使用浏览器访问docker hub: https://hub.docker.com/<br>
在首页搜索框内输入要搜索的镜像名称，比如“hello-world”。进入后，点击TAGS标签，可以查看这个镜像的不同的版本。  </p>
<p><strong>其他镜像仓库</strong><br>
除了Docker Hub官方的镜像仓库以外，还有其他镜像仓库，比如Quay：https://quay.io/  </p>
<h3 id="image-jing-xiang-cao-zuo"><a class="toclink" href="#image-jing-xiang-cao-zuo">image 镜像操作</a></h3>
<p>首先要在本地创建镜像，可以去镜像仓库获取。  </p>
<h4 id="la-qu-jing-xiang"><a class="toclink" href="#la-qu-jing-xiang">拉取镜像</a></h4>
<p>把镜像从镜像仓库拖（pull）下来：</p>
<div class="highlight"><pre><span></span><code>$ docker image pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
1b930d010525: Pull <span class="nb">complete</span> 
Digest: sha256:6540fc08ee6e6b7b63468dc3317e3303aae178cb8a45ed3123180328bcc1d20f
Status: Downloaded newer image <span class="k">for</span> hello-world:latest
$ 
</code></pre></div>

<p>如果不指定tag，默认就是latest。  </p>
<h4 id="cha-kan-xia-zai-de-jing-xiang"><a class="toclink" href="#cha-kan-xia-zai-de-jing-xiang">查看下载的镜像</a></h4>
<p>查看就是ls：</p>
<div class="highlight"><pre><span></span><code>$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              fce289e99eb9        <span class="m">6</span> months ago        <span class="m">1</span>.84kB
$
</code></pre></div>

<p>这里的 IMAGE ID 是镜像的唯一标识。指定镜像的时候可以使用 REPOSITORY 和 TAG，不过本地镜像可以没有这两个属性。但是一定会有 IMAGE ID，通过 IMAGE ID 也可以指明镜像。  </p>
<p>上面显示的ID只是一部分，可以使用--no-trunc参数查看完整的：</p>
<div class="highlight"><pre><span></span><code>$ docker image ls --no-trunc --format <span class="s1">&#39;{{.Repository}}:{{.Tag}} {{.ID}}&#39;</span>
hello-world:latest sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
$ 
</code></pre></div>

<p>在指明镜像的时候，使用完整的或者部分ID都是可以的。  </p>
<h4 id="shan-chu-ben-di-jing-xiang"><a class="toclink" href="#shan-chu-ben-di-jing-xiang">删除本地镜像</a></h4>
<p>如果下错了，或者不用了，也可以删除。命令是<code>docker image rm</code>，或者也可以用<code>docker rmi</code>。<br>
注意，这里不是<code>docker rm</code>，这个命令操作的容器，对应的命令是<code>docker container rm</code>。<br>
这也是建议使用 Management Commands 命令的原因，明确指定要做哪一类的操作。这样在需要操作 image 的时候不会因为误操作而对 container 执行了命令。  </p>
<h3 id="container-rong-qi-cao-zuo"><a class="toclink" href="#container-rong-qi-cao-zuo">container 容器操作</a></h3>
<p>先看下一帮助命令，下面是所有容器相关的子命令：</p>
<div class="highlight"><pre><span></span><code>$ docker container --help

Usage:  docker container COMMAND

Manage containers

Commands:
  attach      Attach <span class="nb">local</span> standard input, output, and error streams to a running container
  commit      Create a new image from a container<span class="s1">&#39;s changes</span>
<span class="s1">  cp          Copy files/folders between a container and the local filesystem</span>
<span class="s1">  create      Create a new container</span>
<span class="s1">  diff        Inspect changes to files or directories on a container&#39;</span>s filesystem
  <span class="nb">exec</span>        Run a <span class="nb">command</span> <span class="k">in</span> a running container
  <span class="nb">export</span>      Export a container<span class="s1">&#39;s filesystem as a tar archive</span>
<span class="s1">  inspect     Display detailed information on one or more containers</span>
<span class="s1">  kill        Kill one or more running containers</span>
<span class="s1">  logs        Fetch the logs of a container</span>
<span class="s1">  ls          List containers</span>
<span class="s1">  pause       Pause all processes within one or more containers</span>
<span class="s1">  port        List port mappings or a specific mapping for the container</span>
<span class="s1">  prune       Remove all stopped containers</span>
<span class="s1">  rename      Rename a container</span>
<span class="s1">  restart     Restart one or more containers</span>
<span class="s1">  rm          Remove one or more containers</span>
<span class="s1">  run         Run a command in a new container</span>
<span class="s1">  start       Start one or more stopped containers</span>
<span class="s1">  stats       Display a live stream of container(s) resource usage statistics</span>
<span class="s1">  stop        Stop one or more running containers</span>
<span class="s1">  top         Display the running processes of a container</span>
<span class="s1">  unpause     Unpause all processes within one or more containers</span>
<span class="s1">  update      Update configuration of one or more containers</span>
<span class="s1">  wait        Block until one or more containers stop, then print their exit codes</span>

<span class="s1">Run &#39;</span>docker container COMMAND --help<span class="err">&#39;</span> <span class="k">for</span> more information on a command.
$ 
</code></pre></div>

<p>主要命令说明：</p>
<ul>
<li>create: 创建一个容器，创建的容器是stop状态，要启动需要start。</li>
<li>start: 启动容器。</li>
<li>stop:: 停止容器。</li>
<li>kill: 强行停止容器。</li>
<li>run: 创建后直接启动容器。这个比较常用。</li>
<li>rm: 删除容器。</li>
<li>pause: 暂停容器。</li>
<li>unpause: 取消暂停。</li>
<li>top: 查看容器的资源消耗，类型Linux的top命令。</li>
<li>ls: 显示容器，类似Linux的ps命令，所以可以直接用 docker ps。</li>
</ul>
<h4 id="run-ming-ling"><a class="toclink" href="#run-ming-ling">run 命令</a></h4>
<p>执行 <code>docker container run --help</code> 查看命令运行的格式：</p>
<div class="highlight"><pre><span></span><code>docker container run [OPTIONS] IMAGE [COMMAND] [ARG...]
</code></pre></div>

<h5 id="qi-dong-rong-qi-shi-zhi-xing-de-ming-ling"><a class="toclink" href="#qi-dong-rong-qi-shi-zhi-xing-de-ming-ling">启动容器时执行的命令</a></h5>
<p>[COMMAND] 是可选的，指定启动容器时运行的命令。
[ARG...] 是像命令传递的参数。</p>
<p>Docker的容器是为了运行单个程序的。<em>就是单个进程，不过容器内部也是可以同时运行多个进程的。</em><br>
每个镜像都有定义默认要运行的程序。基于一个镜像启动容器的时，如果没有指定命令，就执行镜像默认指定的程序。<br>
当然也可以手动指定镜像启动时运行的命令，就是上面的[COMMAND]参数。  </p>
<h5 id="qi-dong-rong-qi-shi-de-xuan-xiang"><a class="toclink" href="#qi-dong-rong-qi-shi-de-xuan-xiang">启动容器时的选项</a></h5>
<p>[OPTIONS] 是一大堆run命令的参数。下面挑几个重要的说：</p>
<ul>
<li>-t, --tty: 分配一个终端。如果要运行为交互式接口，要打开shell，没有终端是无法打开shell的。</li>
<li>-i, --interactive: 进行交换式访问。一般都是-it，两个参数配合使用的。</li>
<li>--name string: 给启动的容器一个名字。</li>
<li>--network string: 启动容器时指定连接的网络。不指定就用默认的，默认加入bridge网络。</li>
<li>--rm: 容器一旦停止，就自动将容器删除。</li>
<li>-d, --detach: 让容器直接运行在后台。否则会一直占据着终端。</li>
</ul>
<h4 id="busybox"><a class="toclink" href="#busybox">busybox</a></h4>
<p>这里来实际的运行个容器，并进行各种操作。<br>
busybox的镜像非常小，它并不是一个系统发行版。最初这个工具是为了在一张软盘上创建一个可引导的 GNU/Linux 系统，这可以用作安装盘和急救盘。它是一个集成了三百多个最常用Linux命令和工具的软件。  </p>
<h5 id="zhi-jie-qi-dong"><a class="toclink" href="#zhi-jie-qi-dong">直接启动</a></h5>
<p>直接将镜像启动为容器：</p>
<div class="highlight"><pre><span></span><code>$ docker container run --name bx0 busybox
$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
$
</code></pre></div>

<p>此时ls也看不到这个容器，不过容器并没有被删除而只是出于停止状态。  </p>
<p>默认只显示运行状态的容器，这里需要加上-a参数：</p>
<div class="highlight"><pre><span></span><code>$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
3a9b8eb31e01        busybox             <span class="s2">&quot;sh&quot;</span>                <span class="m">7</span> minutes ago       Exited <span class="o">(</span><span class="m">0</span><span class="o">)</span> <span class="m">7</span> minutes ago                       bx0
$ 
</code></pre></div>

<p>这里注意一下 COMMAND 字段的值，这个是容器启动时运行的命令。启动容器的时候没有指定，这里就是默认的命令。  </p>
<p>这次启动容器显然是有问题的，先把这个容器删除了，然后继续往下看：</p>
<div class="highlight"><pre><span></span><code>$ docker container rm bx0
</code></pre></div>

<h5 id="qi-dong-bing-kai-qi-zhong-duan"><a class="toclink" href="#qi-dong-bing-kai-qi-zhong-duan">启动并开启终端</a></h5>
<p>这次启动时加上 -it 参数，分配一个 shell 终端：</p>
<div class="highlight"><pre><span></span><code>$ docker run --name bx1 -it busybox
/ <span class="c1"># ls</span>
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ <span class="c1"># ls bin</span>
</code></pre></div>

<p>最后的一条命令 <code>ls bin</code> 可以看到很多命令。这些命令就是 busybox 支持的命令。  </p>
<p>现在是一个 shell 的交互式接口，可以直接运行命令，先看下 ps 命令：</p>
<div class="highlight"><pre><span></span><code>/ <span class="c1"># ps</span>
PID   USER     TIME  COMMAND
    <span class="m">1</span> root      <span class="m">0</span>:00 sh
   <span class="m">10</span> root      <span class="m">0</span>:00 ps
/ <span class="c1"># </span>
</code></pre></div>

<p>可以看到 sh 命令的 PID 是1。PID为1的进程是init进程。  </p>
<blockquote>
<p>Docker 容器启动时，默认会把容器内部第一个进程，也就是pid=1的程序，作为docker容器是否正在运行的依据，如果 docker 容器pid=1的进程挂了，那么docker容器便会直接退出。  </p>
</blockquote>
<p>此时如果退出shell，那么这个容器也就关闭了。第一次启动容器时，没有开启终端，其实就是启动了一个 sh 命令，然后就退出终端了。<br>
所以启动后容器就是停止状态的:</p>
<div class="highlight"><pre><span></span><code>/ <span class="c1"># exit</span>
$ docker container ls -a --format <span class="s1">&#39;{{.Names}}: {{.Status}}&#39;</span>
bx1: Exited <span class="o">(</span><span class="m">126</span><span class="o">)</span> <span class="m">4</span> minutes ago
$ 
</code></pre></div>

<h5 id="zai-ci-qi-dong-rong-qi"><a class="toclink" href="#zai-ci-qi-dong-rong-qi">再次启动容器</a></h5>
<p>容器已经创建好了，这次直接 start 就可以了：</p>
<div class="highlight"><pre><span></span><code>$ docker container start bx1
bx1
$ docker container ls -a --format <span class="s1">&#39;{{.Names}}: {{.Status}}&#39;</span>
bx1: Up <span class="m">2</span> seconds
$ 
</code></pre></div>

<p>但是现在并没有进入到终端。  </p>
<p>用 attach 命令就可以再次进入终端：</p>
<div class="highlight"><pre><span></span><code>$ docker container attach bx1
/ <span class="c1"># ps</span>
PID   USER     TIME  COMMAND
    <span class="m">1</span> root      <span class="m">0</span>:00 sh
    <span class="m">6</span> root      <span class="m">0</span>:00 ps
/ <span class="c1"># </span>
</code></pre></div>

<p>还可以在 start 的时候直接加上 -ai 参数，效果也是一样的：</p>
<div class="highlight"><pre><span></span><code>/ <span class="c1"># exit</span>
$ docker container start bx1 -ai
/ <span class="c1"># </span>
</code></pre></div>

<h5 id="exec-ming-ling"><a class="toclink" href="#exec-ming-ling">exec 命令</a></h5>
<p>最后还有一种方法，不用进入宿主机，直接在宿主机上对容器发送命令，并在宿主机上得到命令的结果：</p>
<div class="highlight"><pre><span></span><code>$ docker container start bx1
bx1
$ docker container <span class="nb">exec</span> bx1 ps
PID   USER     TIME  COMMAND
    <span class="m">1</span> root      <span class="m">0</span>:00 sh
    <span class="m">6</span> root      <span class="m">0</span>:00 ps
$ 
</code></pre></div>

<h4 id="xiao-jie"><a class="toclink" href="#xiao-jie">小结</a></h4>
<p>这里有张图，描述了容器的各个常用命令和容器状态的转换：<br>
<img alt="Docker命令" src="/images/docker/01_docker-commands.png"><br>
图里有个OOM（Out Of Memory）内存不足，是内存使用过多。OOM状态的容器会被kill掉，来保证系统的可持续运行。<br>
OOM被kill之后就看容器的机制，决定是否会自动重启，否则就进入stopped状态。  </p>
      </div>
      <div class="back-to-top">
        <a href="/">HOME</a>
        <a href="#top">TOP</a>
      </div>
    </article>
  </div>
<!-- end article -->
<!-- 页面往下滚动一段之后才会显示TOC -->
<script>
  window.onscroll = function() {
    var tocbox = document.getElementsByClassName('toc')[0];
    var osTop = document.documentElement.scrollTop || document.body.scrollTop;
    var osWidth = document.documentElement.scrollWidth || document.body.scrollWidth;
    // console.log(osTop)
    if (osTop>300 && osWidth>865) {
      tocbox.style.display = "block"
    }
    if (osTop<300 || osWidth<865) {
      tocbox.style.display = "none"
    }
  }
</script>
                <footer>
                    <div class="icons">
                    </div>
                    <span id="busuanzi_container_page_pv" style="padding: 10px">本文阅读量<span id="busuanzi_value_page_pv"></span>次</span>
                    <span id="busuanzi_container_site_pv" style="padding: 10px">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span>
                    <span id="busuanzi_container_site_uv" style="padding: 10px">本站总访客数<span id="busuanzi_value_site_uv"></span>人</span>
                    <p>© <script>document.write(moment().format('YYYY'));</script> 749B</p>
                </footer>
        </div>
</body>
</html>